from django.utils.datastructures  import SortedDict
from sitepal.sitebase.util        import iterappmodules
from sitepal.sitetheme            import DEFAULT_THEME_NAME
from sitepal.sitetheme.exceptions import ThemeLoadError
from sitepal.sitetheme.media      import Medium
from sitepal.sitetheme.models     import Theme
from sitepal.sitetheme.renderers  import ApplicationRenderer,ThemeRenderer

class BaseThemeLoader(object):
    def load(self,theme):
        assert isinstance(theme,Theme)
        theme._headers            = None
        theme._media              = SortedDict()
        theme._theme_render_funcs = {}
        theme._appl_render_funcs  = {}

    def load_media(self,theme,module):
        if hasattr(module,'media'):
            try:
                for medium in module.media:
                    if not isinstance(medium,Medium):
                        raise ThemeLoaderror,"Not a medium: {0!r}".format(medium)
                    medium.theme_setup(theme)
                    theme._media[medium.name] = medium
#                    print "{0!r}, {1}".format(medium,medium.url)
            except TypeError:
                raise ThemeLoadError,"Medium must be an iterable"

class DefaultThemeLoader(BaseThemeLoader):
    _additional_submodules = set()

    @classmethod
    def register(cls,submodule):
        assert isinstance(submodule,basestring)
        cls._additional_submodules.add(submodule)

    def load(self,theme):
        super(DefaultThemeLoader,self).load(theme)
        if theme.name != DEFAULT_THEME_NAME:
            raise ThemeLoadError,"Must be default theme"
        for app_label,module in iterappmodules('siteapp.theme'):
            self.load_media(theme,module)
            if app_label == 'sitetheme':
                if not hasattr(module,'renderer'):
                    raise ThemeLoadError,"Invalid theme, no theme renderer defined"
                renderer_class = module.renderer
                if not issubclass(renderer_class,ThemeRenderer):
                    raise ThemeLoadError,"Invalid render class for '{0}'".format(module.__name__)
                theme._theme_render_funcs = renderer_class(theme=theme).contribute_to_theme()
            else:
                self.load_module(theme,app_label,module)
        for submodule in self._additional_submodules:
            for app_label,module in iterappmodules(submodule):
                self.load_media(theme,module)
                self.load_module(theme,app_label,module)

    def load_module(self,theme,app_label,module):
        if hasattr(module,'renderer'):
            renderer_class = module.renderer
            if not issubclass(renderer_class,ApplicationRenderer):
                raise ThemeLoadError,"Invalid render class for '{0}'".format(module.__name__)
            theme._appl_render_funcs.update(renderer_class(theme=theme).contribute_to_theme())

